
#include "soldier.h"
#include "towerinfo.h"
#include "levelmanager.h"
#include "resourcemanager.h"
#include "gamemanager.h"
#include "gameplayscene.h"
#include "CCSkeletalSprite.h"
#include "tower.h"
#include "rallypoint.h"

#define __super			Unit

Soldier::Soldier() :
	myPositionIndex(0)
	, rangeCircle(nullptr)
{

}

Soldier::~Soldier() {
	if(myFlag) {
		myFlag->onSoldierDied(myPositionIndex);
	}
}


void Soldier::set( const string& name, const Point& pos, GamePlayScene* scene )
{
	__super::set(name, pos, scene);

	rangeCircle = createRangeCircle();
	rangeCircle->setVisible(false);
	gamePlayScene->addSceneNode(rangeCircle);
}

bool Soldier::update( float ticks )
{
	sprintf(buf, "%0.0f,%0.0f", X_SCALE(position.x), Y_SCALE(position.y));
	_labelDebug->setString(buf);

	sprite->update(ticks);
	updateBullets(ticks);

	switch (state)
	{
	case UnitState::birth:
		handleStateBirth(ticks);
		break;
	case UnitState::walk_to_flag:
	case UnitState::head_to_fight:
	case UnitState::walk_to_mining:
	case UnitState::back_to_camp:
		handleStateWalk(ticks);
		break;
	case UnitState::stand:
		handleStateStand(ticks);
		break;
	case UnitState::melee:
		handleStateMelee(ticks);
		break;
	case UnitState::shoot:
		handleStateShoot(ticks);
		break;
	case UnitState::cast:
		handleStateCast(ticks);
		break;
	case UnitState::reload:
		handleStateReload(ticks);
		break;
	case UnitState::dying:
		handleStateDying(ticks);
		break;
	case UnitState::work:
		handleStateWork(ticks);
		break;
	default:
		break;
	}

	return true;
}

void Soldier::handleStateBirth( float ticks )
{
	myPositionIndex = myFlag->getSoldierPositionIndex();
	regroup();
}

void Soldier::handleStateWalk( float ticks )
{
	if(!move(ticks)) {
		transformState(UnitState::stand);
	}
}

void Soldier::handleStateWork( float ticks )
{

}

void Soldier::handleStateStand( float ticks )
{

}

void Soldier::handleStateMelee( float ticks )
{

}

void Soldier::handleStateShoot( float ticks )
{

}

void Soldier::handleStateCast( float ticks )
{

}

void Soldier::handleStateDying( float ticks )
{
	if(sprite->animationIsDone()) {
		transformState(UnitState::died);
	}
}

void Soldier::handleStateReload( float ticks )
{
	_ticks += ticks;
	if(_ticks >= attribute.interval) {
		transformState(previousState);
	} else if(!target) {
		transformState(UnitState::stand);
	}
}

void Soldier::onAttack( EventData* event )
{
	if(strcmp(event->name, "melee") == 0)  {
		attack();
	} else if(strcmp(event->name, "shoot") == 0)  {
		shoot();
	} else if(strcmp(event->name, "cast") == 0)  {
		cast();
	}
}

void Soldier::attack() {
}

void Soldier::shoot() {
}

void Soldier::cast() {
}

void Soldier::setFlag(Flag* flag)
{
	myFlag = flag;

	static const Color3B LIFEBAR_COLOR_NAMES[] = {
		Color3B::BLUE,
		Color3B(0, 102, 51),
		Color3B::ORANGE,
		Color3B::MAGENTA,
		Color3B::RED,
		Color3B(0, 204, 255),
		Color3B::YELLOW,
	};

	int index = (int)myFlag->color;
	_sprLifebar->setColor(LIFEBAR_COLOR_NAMES[index]);
}

Sprite* Soldier::createRangeCircle()
{
	Sprite* circle = Sprite::create();
	circle->setTag(TAG_NO_ZORDER);

	float w;
	for(int i = 0; i < 8; i++) {
		Sprite* spr = CREATE_SPRITE("textures/units/range_circle.png");
		spr->setScale(1.0f);
		spr->setAnchorPoint(Point::ZERO);
		spr->setRotation(i * 45.0f);
		spr->setPosition(Point::ZERO);
		spr->setZOrder(-1);

		if(i == 0) {
			w = spr->getContentSize().width;
		}

		circle->addChild(spr);
	}

	float scale = attribute.range / w;
	circle->setScaleX(GM->minscale * scale);
	circle->setScaleY(GM->minscale * scale * 0.7f);

	return circle;
}

bool Soldier::move( float ticks )
{
	bool ret = __super::move(ticks);

	rangeCircle->setPosition(SCALE_PT(position));

	return ret;
}

void Soldier::regroup()
{
	if(target && target->target == this) {
		target->target = nullptr;
	}

	target = nullptr;

	targetPosition = myFlag->position + myFlag->soldierPositions[myPositionIndex];
	if(targetPosition.equals(position)) {
		return;
	}

	float angle = (targetPosition - position).getAngle();
	speed = (Point(attribute.speed, 0)).rotateByAngle(Point::ZERO, angle);

	sprite->setFlipX(targetPosition.x < position.x);

	transformState(UnitState::walk_to_flag);
}
